﻿// Author: AustralTek 
// Create date: 2010/05/04
// http://www.australtek.com
// Copyright: 2009 - 2010

(function () {
    try {
        function _DropDownPicker(obj, options) {
            /*--------------------------*/
            /*----Private properties----*/
            /*--------------------------*/
            var containerAux;
            var container;
            var pickerList;
            var selectList;
            var siblingsGroups;
            var LoadingContainer;
            var loading;
            var privateParameters;

            /* Sets and Overrides certains */
            function _initialize(obj, options) {
                try {
                    containerAux = obj;
                    container = null;
                    pickerList = [];
                    selectList = [];
                    siblingsGroups = [];

                    LoadingContainer = document.createElement('div');
                    LoadingContainer.id = 'loading_' + containerAux.id;
                    LoadingContainer.style.top = '0px';
                    var loadingOptions = { 'Type': 0, 'Title': 'Loading', 'Animate': true };
                    loading = new DisplayPoster(LoadingContainer, loadingOptions);
                    LoadingContainer.style.position = 'relative';
                    containerAux.appendChild(LoadingContainer);
                    loading.SetVisible(false);

                    privateParameters = new PrivateParameters(options);
                    privateParameters.TransparentOption = privateParameters.TransparentOption || null;
                    privateParameters.FormatTable = privateParameters.FormatTable || null;
                    privateParameters.DisplayPoster = privateParameters.DisplayPoster || null;

                    privateParameters.Version.Class = 'DropDownPicker';
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _refreshData(parameters) {
                try {
                    var url = privateParameters.URL;
                    var options = {}; options.data = {};
                    options.data.DatabaseParameters = privateParameters.DatabaseParameters;
                    options.data.JSONFile = privateParameters.JSONFile;
                    for (var conParam in privateParameters.ConnectionParameters)
                        options[conParam] = privateParameters.ConnectionParameters[conParam];
                    if ((parameters) && (parameters.Version))
                        options.data.DatabaseParameters.QueryParameters = parameters.GetQueryParameters();
                    else options = (parameters) ? parameters : options;

                    options.data.Namespace = privateParameters.Version.Namespace;
                    options.data.Class = privateParameters.Version.Class;

                    options.onRequest = function () {
                        try {
                            if (privateParameters.DisplayPoster)
                                loading.SetVisible(true);
                        }
                        catch (Error) { privateParameters.Events.onError(Error); }
                    };
                    options.onSuccess = function (data) {
                        try {
                            if ((data) && (!data.message)) {
                                pickerList = data.pickerList;
                                _redraw();
                            }
                        }
                        catch (Error) { privateParameters.Events.onError(Error); }
                    };
                    options.onFailure = function (error) {
                        privateParameters.Events.onFailure(error.statusText);
                    };

                    RequestJSON(url, options);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _redraw() {
                try {
                    if ((pickerList) && (pickerList.length > 0)) {
                        if (selectList.length == 0) {

                            container = document.createElement('div');
                            container.className = 'dropDownPickerContainers';
                            containerAux.appendChild(container);

                            /* Creates the list who contains the pickers. */
                            var table = document.createElement('table');
                            table.className = 'dropDownPickerTables';
                            table.cellSpacing = 0;
                            container.appendChild(table);

                            var tableBody = document.createElement('tbody');
                            table.appendChild(tableBody);

                            var tr = document.createElement('tr');
                            tr.className = 'dropDownPickerTableTrs';
                            tableBody.appendChild(tr);

                            if (privateParameters.FormatTable) {
                                var formatTableActive = true;
                                privateParameters.FormatTable.structsBuildedCount = 0;
                            }
                            else
                                var formatTableActive = false;

                            for (var iPickerIndex = 0; iPickerIndex < pickerList.length; iPickerIndex++) {
                                var select = pickerList[iPickerIndex];

                                var oPicker = document.createElement('div');
                                oPicker.className = 'pickerContainers';

                                var oTitle = document.createElement('div');
                                oPicker.appendChild(oTitle);
                                oTitle.className = 'pickerTitles';
                                oTitle.innerHTML = trim(select.title);

                                /* Creates the select box. */
                                var oSelect = document.createElement('select');
                                oSelect.className = 'pickers';
                                oSelect.selectID = select.id;
                                oSelect.selectsChildrenIndexList = null;
                                oSelect.empty = true;
                                addEventHandler(oSelect, 'onchange', privateParameters.Events.onChange);

                                oPicker.id = 'Picker-' + trim(select.name);
                                oSelect.id = 'Select-' + trim(select.name);

                                var oselectListItem = {};
                                oselectListItem.title = trim(select.name);
                                oselectListItem.name = trim(select.name);
                                oselectListItem.select = oSelect;

                                selectList.push(oselectListItem);
                                oPicker.appendChild(oSelect);

                                oSelect.Attrib = {};
                                if (select.Attrib) {
                                    for (var attribute in select.Attrib) {
                                        switch (attribute.toUpperCase()) {
                                            case 'CHANGE':
                                                var func = select.Attrib[attribute];
                                                oSelect.Attrib.change = eval(func);
                                                removeEventHandler(oSelect, 'onchange', privateParameters.Events.onChange);
                                                addEventHandler(oSelect, 'onchange', _oSelectChange);
                                                break;
                                            case 'MAXLENGTH':
                                                var optionValueLengthLimit = parseInt(eval('select.Attrib.' + attribute));
                                                oSelect.Attrib.maxLength = eval('select.Attrib.' + attribute);
                                                break;
                                            case 'HIDDEN':
                                                oSelect.parentElement.style.display = 'none';
                                                oSelect.Attrib.hidden = true;
                                                break;
                                            case 'SIBLINGSSELECTS':
                                                var siblingsSelects = eval('select.Attrib.' + attribute);
                                                if ((siblingsSelects.siblingGroup != null) && (siblingsSelects.siblingValue != null)) {
                                                    oSelect.Attrib.siblingsSelects = {};
                                                    oSelect.Attrib.siblingsSelects.siblingGroup = siblingsSelects.siblingGroup;
                                                    oSelect.Attrib.siblingsSelects.siblingValue = siblingsSelects.siblingValue;
                                                    if (siblingsGroups[siblingsSelects.siblingGroup]) {
                                                        siblingsGroups[siblingsSelects.siblingGroup].push(oSelect);
                                                        /* Inserts the siblings selects in the same td.*/
                                                        siblingsGroups[siblingsSelects.siblingGroup][0].parentElement.parentElement.appendChild(oSelect.parentElement);
                                                    }
                                                    else
                                                        siblingsGroups[siblingsSelects.siblingGroup] = [oSelect];
                                                }
                                                break;
                                        }
                                    }
                                }

                                if ((oSelect.Attrib.siblingsSelects == null) || (siblingsGroups[oSelect.Attrib.siblingsSelects.siblingGroup].length == 1)) {
                                    var td = document.createElement('td');
                                    td.className = 'pickerTableTds';
                                    tr.appendChild(td);
                                    td.appendChild(oPicker);

                                    if (formatTableActive == true) {
                                        if (_formatingTable() == true) {
                                            tr = document.createElement('tr');
                                            tableBody.appendChild(tr);
                                        }
                                    }
                                }

                                /* Adds options.*/
                                if ((select.options) && (select.options.length > 0)) {
                                    var bHasParent = false;
                                    var parentDefaultValue = null;

                                    /* Inserts options. */
                                    for (var iSelectOptionIndex = 0; iSelectOptionIndex < select.options.length; iSelectOptionIndex++) {
                                        var bAddOption = true;
                                        var sOptionInnerHtml = "";
                                        var option = select.options[iSelectOptionIndex];
                                        if (option) {
                                            /* Inserts or not the first option. It can be a title or empty. */
                                            if (iSelectOptionIndex == 0) {
                                                if (!privateParameters.TransparentOption)
                                                    bAddOption = false;
                                                else
                                                    sOptionInnerHtml = option.legend;

                                                /* Looks for parent select.
                                                Only looks for parent select in the first option because that option
                                                have the "title" of the parent to search it. */
                                                if (select.parentID) {
                                                    bHasParent = true;

                                                    var parentSelect = selectList[select.parentID - 1].select;

                                                    /* In the list of Selects adds to the select parent the index of its child. */
                                                    if (parentSelect.selectsChildrenIndexList == null)
                                                        parentSelect.selectsChildrenIndexList = [];
                                                    parentSelect.selectsChildrenIndexList.push(select.id);

                                                    /* When parent changes, updates its chidlren. */
                                                    /* If the select already has a change event, executes both. */
                                                    removeEventHandler(parentSelect, 'onchange', privateParameters.Events.onChange);
                                                    if ((parentSelect.Attrib) && (parentSelect.Attrib.change)) {
                                                        removeEventHandler(parentSelect, 'onchange', _oSelectChange);
                                                        addEventHandler(parentSelect, 'onchange', _parentSelectChange2);
                                                    }
                                                    else
                                                        addEventHandler(parentSelect, 'onchange', _parentSelectChange);

                                                    if (parentDefaultValue == null)
                                                        parentDefaultValue = parentSelect.value;
                                                }
                                            }
                                            else {
                                                /* Inserts only  the options who has the same "value" that its parent. */
                                                if (bHasParent) {
                                                    if (option.parentValue.toString() != parentDefaultValue)
                                                        bAddOption = false;
                                                }
                                                if (bAddOption)
                                                    sOptionInnerHtml = option.legend;
                                            }

                                            if (bAddOption) {
                                                if ((oSelect.empty != false) && ((option.value) || (option.value != 'null'))
                                                        && ((parentDefaultValue == null) || (parentDefaultValue == 'null')))
                                                    oSelect.empty = false

                                                var oSelectOption = document.createElement('option');


                                                oSelectOption.value = ((option.value) || (option.value == 0)) ? parseInt(option.value) : null;

                                                /* Cuts the string if it is necesary.*/
                                                if ((optionValueLengthLimit) && (sOptionInnerHtml.length > optionValueLengthLimit))
                                                    sOptionInnerHtml = sOptionInnerHtml.replace(sOptionInnerHtml, sOptionInnerHtml.slice(0, optionValueLengthLimit) + '...');

                                                oSelectOption.innerHTML = sOptionInnerHtml;

                                                if ((option.defaultSelected) && (parseInt(option.defaultSelected) == 1))
                                                    oSelectOption.selected = true;

                                                oSelect.appendChild(oSelectOption);
                                            }
                                        }
                                    }

                                    /* If doesn't have options, sets "No options".*/
                                    if ((oSelect.length == 1) && (oSelect[0].value == 'null') & (oSelect.empty != false))
                                        oSelect[0].innerHTML = 'No options';

                                    if (oSelect.length == 0) {
                                        var selectOption = document.createElement('option');
                                        selectOption.value = null;
                                        selectOption.innerHTML = 'No options';
                                        oSelect.appendChild(selectOption);
                                    }
                                }
                            }
                        }
                    }
                    loading.SetVisible(false);
                    setTimeout(privateParameters.Events.onComplete, 1);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            /*-----------------------------------------------------------------------*/
            /*-----------------------------------------------------------------------*/
            /*-----------------------------------------------------------------------*/
            /* Initializes properties*/
            _initialize(obj, options);
            /*-----------------------------------------------------------------------*/
            /*-----------------------------------------------------------------------*/
            /*-----------------------------------------------------------------------*/

            /*-----------------------*/
            /*----Private methods----*/
            /*-----------------------*/
            /* Selects the first option of the pickers.*/
            function _clearPickers() {
                try {
                    for (var iSelectIndex = 0; iSelectIndex < selectList.length; iSelectIndex++) {
                        var select = selectList[iSelectIndex].select;
                        select[0].selected = true;
                        if ((select.selectsChildrenIndexList) && (select.selectsChildrenIndexList.length > 0))
                            _updateSelectsChildren(null, select);
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            };
            /* Returns an object with the filters.*/
            function _getResults(options) {
                var ret;
                try {
                    options = options || { DBEngine: 'SQLServer', paramsWishList: null }; //DBEngine = SQL Server by default.
                    options.DBEngine = options.DBEngine || 'SQLServer'; //DBEngine = SQL Server by default.

                    switch (options.DBEngine.toUpperCase()) {
                        case 'SQLSERVER': break;
                        case 'ORACLE': break;
                        default: throw Error;
                    };

                    ret = new QueryParameters({ DBEngine: options.DBEngine });

                    if (options.paramsWishList) {
                        for (var iParamWish = 0; iParamWish < options.paramsWishList.length; iParamWish++) {
                            for (var iSelectIndex = 0; iSelectIndex < selectList.length; iSelectIndex++) {
                                if (options.paramsWishList[iParamWish] == selectList[iSelectIndex].name)
                                    ret.Add(selectList[iSelectIndex].name, pickerList[iSelectIndex].typesList[options.DBEngine], selectList[iSelectIndex].select.value);
                            }
                        }
                    }
                    else {
                        for (var iSelectIndex = 0; iSelectIndex < selectList.length; iSelectIndex++) {
                            ret.Add(selectList[iSelectIndex].name, pickerList[iSelectIndex].typesList[options.DBEngine], selectList[iSelectIndex].select.value);
                        }
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
                return ret;
            };
            function _upsertSelectOptions(selectID, optionsData) {
                try {
                    if (selectList[selectID - 1])
                        var select = selectList[selectID - 1].select;
                    else
                        return null;

                    for (var iOptionData = 0; iOptionData < optionsData.length; iOptionData++) {
                        var newOptionData = optionsData[iOptionData];
                        var picker = pickerList[select.selectID - 1];
                        var parentSelect = (picker.parentID != 0) ? selectList[picker.parentID - 1].select : null;

                        /* If the no one option has the same value or the same legend that newOptionData, just add
                        the new data and the new select option.*/
                        picker.options.push(newOptionData);

                        /* Sets the last option selected by default these property "defaultSelected" to 0.*/
                        for (var iPickerOption = 0; iPickerOption < picker.options.length; iPickerOption++) {
                            var pickerOption = picker.options[iPickerOption];
                            if (pickerOption.defaultSelected == 1) {
                                pickerOption.defaultSelected = 0;
                                break;
                            }
                        }

                        /* Only update the select option if "parentSelect" is not null and the "parentSelect.value"
                        is the same that "newOptionData.parentValue".*/
                        if ((parentSelect == null) || (newOptionData.parentValue.toString() == parentSelect.value)) {
                            var option = document.createElement('option');

                            /* Cuts the string if it is necesary.*/
                            if ((picker.Attrib) && (picker.Attrib.maxLenght) && (newOptionData.legend.length > picker.Attrib.maxLenght))
                                newOptionData.legend = newOptionData.legend.replace(newOptionData.legend, newOptionData.legend.slice(0, picker.Attrib.maxLenght) + '...');

                            option.innerHTML = newOptionData.legend;
                            option.value = ((newOptionData.value) || (newOptionData.value == 0)) ? newOptionData.value : null;

                            if (parseInt(newOptionData.defaultSelected) == 1) {
                                /* Removes all change event to prevents automatic trigger of these 
                                when updates the options of the child select.*/
                                _removeChangeEvents(select);

                                option.selected = true;

                                _attachChangeEvents(select);
                            }

                            select.appendChild(option);
                        }
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            };
            /* Updates the select value and, if it has selects children, updates them.*/
            function _updateSelect(selectID, value) {
                try {
                    if ((selectID) && (value)) {
                        var select = selectList[selectID - 1].select;

                        /* Removes all change event to prevents automatic trigger of these 
                        when updates the options of the child select.*/
                        _removeChangeEvents(select);

                        for (var iOption = 0; iOption < select.length; iOption++) {
                            /* Searchs the option who contains this value and selects it. */
                            if (select[iOption].value == value.toString()) {
                                select[iOption].selected = true;

                                if ((select.selectsChildrenIndexList) && (select.selectsChildrenIndexList.length > 0))
                                    _updateSelectsChildren(null, select);

                                /* Attach again all the change events what were have been removed.*/
                                _attachChangeEvents(select);
                                return true;
                            }
                        }
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
                return false;
            };
            /* Updates the selects children of the select who fire this event. */
            function _updateSelectsChildren(e, parentSelect) {
                try {
                    if ((parentSelect) && (parentSelect.selectsChildrenIndexList)) {
                        var selectsChildrenIndexList = parentSelect.selectsChildrenIndexList;
                        var selectParentValue = parentSelect.value;
                    }
                    else {
                        var target = e.srcElement || e.target;
                        if (target.selectsChildrenIndexList) {
                            var selectsChildrenIndexList = target.selectsChildrenIndexList;
                            var selectParentValue = target.value;
                        }
                        else
                            return null;
                    }

                    for (var index = 0; index < selectsChildrenIndexList.length; index++) {
                        var select = selectList[selectsChildrenIndexList[index] - 1].select;

                        /* Removes all change event to prevents automatic trigger of these 
                        when updates the options of the child select.*/
                        _removeChangeEvents(select);

                        /* Deletes all select's options. */
                        select.length = 0;
                        select.empty = true;

                        var pickersSelect = pickerList[selectsChildrenIndexList[index] - 1];
                        var optionValueLengthLimit = ((pickersSelect.Attrib) && ((pickersSelect.Attrib.maxLength) && (parseInt(pickersSelect.Attrib.maxLength) > 0)))
                                        ? pickersSelect.Attrib.maxLength : null;

                        /* Inserts options. */
                        for (var pickerSelectOptionIndex = 0; pickerSelectOptionIndex < pickersSelect.options.length; pickerSelectOptionIndex++) {
                            var bAddOption = true;
                            var option = pickersSelect.options[pickerSelectOptionIndex];
                            var optionInnerHtml = "";

                            /* It doesn't matter that the value of the first option does't be equals that the "selectParentValue".
                            It will insert always. */
                            if (pickerSelectOptionIndex == 0) {
                                if (!privateParameters.TransparentOption)
                                    bAddOption = false;
                                else
                                    optionInnerHtml = option.legend;
                            }
                            else {
                                /* Inserts only  the options who has the same "value" that its parent. */
                                if (option.parentValue.toString() != selectParentValue)
                                    bAddOption = false;
                                else
                                    optionInnerHtml = option.legend;
                            }

                            if (bAddOption) {
                                if ((select.empty != false) && ((option.value) || (option.value != 'null'))
                                    && ((selectParentValue == null) || (selectParentValue == 'null')))
                                    select.empty = false

                                var selectOption = document.createElement('option');

                                selectOption.value = ((option.value) || (option.value == 0)) ? parseInt(option.value) : null;

                                if ((optionValueLengthLimit) && (optionInnerHtml.length > optionValueLengthLimit))
                                    optionInnerHtml = optionInnerHtml.replace(optionInnerHtml, optionInnerHtml.slice(0, optionValueLengthLimit) + '...');

                                selectOption.innerHTML = optionInnerHtml;

                                if ((option.defaultSelected) && (parseInt(option.defaultSelected) == 1))
                                    selectOption.selected = true;

                                select.appendChild(selectOption);
                            }
                        }

                        if ((select.length == 1) && (select[0].value == 'null') && (select.empty != false))
                            select[0].innerHTML = 'No options';

                        if (select.length == 0) {
                            var selectOption = document.createElement('option');
                            selectOption.value = null;
                            selectOption.innerHTML = 'No options';
                            select.appendChild(selectOption);
                        }

                        if ((select.selectsChildrenIndexList) && (select.selectsChildrenIndexList.length > 0))
                            _updateSelectsChildren(null, select);

                        /* Attach again all the change events what were have been removed.*/
                        _attachChangeEvents(select);
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            };
            /* Selects the option that contains this value.
            If the options inserted don't have this value, updates the select.
            Does the same with the parent if it is necesary. */
            function _updateSelectOnReverse(selectIndex, value) {
                try {
                    if ((selectIndex) && (value)) {
                        var actualSelect = selectList[selectIndex - 1];

                        /* Removes all change event to prevents automatic trigger of these 
                        when updates the options of the child select.*/
                        if ((actualSelect.Attrib) && (actualSelect.Attrib.change))
                            removeEventHandler(actualSelect, 'onchange', _parentSelectChange2);
                        else
                            removeEventHandler(actualSelect, 'onchange', _parentSelectChange);

                        for (var i = 0; i < actualSelect.select.length; i++) {
                            /* Searchs the option who contains this value and selects it. */
                            if (actualSelect.select[i].value == value.toString()) {
                                actualSelect.select[i].selected = true;

                                if ((actualSelect.select.selectsChildrenIndexList) && (actualSelect.select.selectsChildrenIndexList.length > 0))
                                    _updateSelectsChildren(null, actualSelect.select);

                                /* Attach again all the change events what were have been removed.*/
                                _attachChangeEvents(actualSelect);
                                return true;
                            }
                        }
                        /* If the options inserted doesn't have this value, looks in all options of the picker. */
                        for (var j = 0; j < pickerList[selectIndex - 1].options.length; j++) {
                            if (pickerList[selectIndex - 1].options[j].value == value.toString()) {
                                /* Sets the option that will be selected.*/
                                for (var iPickerOption = 0; iPickerOption < pickerList[selectIndex - 1].options.length; iPickerOption++) {
                                    var pickerOption = pickerList[selectIndex - 1].options[iPickerOption];
                                    if (pickerOption.defaultSelected = 1) {
                                        pickerOption.defaultSelected = 0;
                                        break;
                                    }
                                }

                                pickerList[selectIndex - 1].options[j].defaultSelected = 1;

                                var pickerParentValue = pickerList[selectIndex - 1].options[j].parentValue;
                                var picker = pickerList[selectIndex - 1];

                                /* Does the same with the parent.
                                The child select will be updated by the parent.*/
                                _updateSelectOnReverse(picker.parentID, pickerParentValue);

                                /* Attach again all the change events what were have been removed.*/
                                _attachChangeEvents(actualSelect);
                                return true;
                            }
                        }
                        return false;
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            };
            function _manipulateSelect(selectID, hidden) {
                try {
                    if ((selectID) && (selectID > 0)) {
                        var picker = pickerList[selectID - 1];
                        var select = selectList[selectID - 1].select;

                        picker.Attrib.hidden = select.Attrib.hidden = hidden;

                        select.parentElement.style.display = (hidden == true) ? 'none' : '';
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }
            function _manipulateSiblingsSelects(groupIndex, siblingValue) {
                try {
                    for (var iGroup = 0; iGroup < siblingsGroups.length; iGroup++) {
                        if (iGroup == groupIndex) {
                            var group = siblingsGroups[iGroup];
                            for (var iSelect = 0; iSelect < group.length; iSelect++) {
                                var select = group[iSelect];
                                var siblingsValues = select.Attrib.siblingsSelects.siblingValue;
                                for (var iSiblingValue = 0; iSiblingValue < siblingsValues.length; iSiblingValue++) {
                                    if (siblingsValues[iSiblingValue] == siblingValue) {
                                        select.parentElement.style.display = '';
                                        select.parentElement.style.zIndex = 1;
                                        select.Attrib.hidden = false;
                                        break;
                                    }
                                    else if (iSiblingValue == siblingsValues.length - 1) {
                                        select.parentElement.style.display = 'none';
                                        select.parentElement.style.zIndex = -1;
                                        select.Attrib.hidden = true;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            /* Format the table container in certains count of column or rows. */
            function _formatingTable() {
                try {
                    if ((privateParameters.FormatTable.type) && (privateParameters.FormatTable.type != '')
                            && (privateParameters.FormatTable.count) && (privateParameters.FormatTable.count > 0)) {
                        var type = privateParameters.FormatTable.type;
                        var count = privateParameters.FormatTable.count;

                        if (type.toUpperCase() == 'BYCOLUMN') {
                            privateParameters.FormatTable.structsBuildedCount++;
                            if (privateParameters.FormatTable.structsBuildedCount == count) {
                                privateParameters.FormatTable.structsBuildedCount = 0;
                                return true;
                            }
                            else
                                return false;
                        }

                        if (type.toUpperCase() == 'BYROW') {
                        }
                    }
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _removeChangeEvents(select) {
                try {
                    removeEventHandler(select, 'onchange', privateParameters.Events.onChange);
                    removeEventHandler(select, 'onchange', _parentSelectChange2);
                    removeEventHandler(select, 'onchange', _parentSelectChange);
                    removeEventHandler(select, 'onchange', _oSelectChange);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _attachChangeEvents(select) {
                try {
                    if (select.selectsChildrenIndexList) {
                        if ((select.Attrib) && (select.Attrib.change))
                            addEventHandler(select, 'onchange', _parentSelectChange2);
                        else
                            addEventHandler(select, 'onchange', _parentSelectChange);
                    }
                    else if ((select.Attrib) && (select.Attrib.change))
                        addEventHandler(select, 'onchange', _oSelectChange);
                    else
                        addEventHandler(select, 'onchange', privateParameters.Events.onChange);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            /*--------------------*/
            /*-------Events-------*/
            /*--------------------*/

            function _oSelectChange(e) {
                try {
                    privateParameters.Events.onChange(e);
                    var target = e.srcElement || e.target;
                    target.Attrib.change(e);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _parentSelectChange(e) {
                try {
                    _updateSelectsChildren(null, e.srcElement || e.target);
                    privateParameters.Events.onChange(e);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            function _parentSelectChange2(e) {
                try {
                    _parentSelectChange(e);
                    _oSelectChange(e);
                }
                catch (Error) { privateParameters.Events.onError(Error); }
            }

            /*--------------------*/
            /*-------Public-------*/
            /*--------------------*/

            /*----------------------------*/
            /* ----Getters and Setters----*/
            /*----------------------------*/
            this.GetDatabaseEngine = function () { return DatabaseConnection.GetDatabaseEngine(privateParameters.DatabaseEngine); };
            this.SetDatabaseEngine = function (newDatabaseEngine) { DatabaseConnection.SetDatabaseEngine(privateParameters, newDatabaseEngine); };
            this.GetConnectionStringName = function () { return DatabaseConnection.GetConnectionStringName(privateParameters.ConnectionStringName); };
            this.SetConnectionStringName = function (newConnectionStringName) { DatabaseConnection.SetConnectionStringName(privateParameters, newConnectionStringName); };
            this.GetTablesCount = function () { return DatabaseConnection.GetTablesCount(privateParameters.TablesCount); };
            this.SetTablesCount = function (newTablesCount) { DatabaseConnection.SetTablesCount(privateParameters, newTablesCount); };
            this.GetProcedure = function () { return DatabaseConnection.GetProcedure(privateParameters.Procedure); };
            this.SetProcedure = function (newProcedure) { DatabaseConnection.SetProcedure(privateParameters, newProcedure); };

            this.GetUrl = function () {
                return privateParameters.Procedure;
            };
            this.SetUrl = function (newUrl) {
                privateParameters.URL = newUrl;
            };

            this.GetSelectList = function () {
                return selectList;
            };

            this.GetPoster = function () {
                return poster;
            };
            /*----------------------*/
            /*--------Methods-------*/
            /*----------------------*/
            this.RefreshData = function (data) {
                _refreshData(data);
            };
            this.ClearPickers = function () {
                _clearPickers();
            };
            this.GetResults = function (options) {
                return _getResults(options);
            }
            this.UpsertSelectOptions = function (selectID, optionsData) {
                _upsertSelectOptions(selectID, optionsData)
            };
            this.UpdateSelect = function (selectID, value) {
                return _updateSelect(selectID, value);
            };
            this.UpdateSelectsChildren = function (e, parentSelect) {
                _updateSelectsChildren(e, parentSelect);
            };
            this.UpdateSelectOnReverse = function (selectIndex, value) {
                return _updateSelectOnReverse(selectIndex, value);
            };
            this.ManipulateSelect = function (selectID, hidden) {
                _manipulateSelect(selectID, hidden);
            }
            this.ManipulateSiblingsSelects = function (groupIndex, siblingValue) {
                _manipulateSiblingsSelects(groupIndex, siblingValue);
            }
        }

        window.DropDownPicker = function (obj, instanceOptions) { return new _DropDownPicker(obj, instanceOptions); };
    }
    catch (Error) { window.status = Error.message; }
})();